package com.fengyi.library.service.impl;

import com.fengyi.library.model.Book;
import com.fengyi.library.repository.BookRepository;
import com.fengyi.library.DTO.BookDTO;
import com.fengyi.library.service.BookService;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BookServiceImpl implements BookService {

    private final BookRepository bookRepository;

    @Autowired
    public BookServiceImpl(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    @Override
    public BookDTO findById(Integer id) {
        Book book = bookRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("图书不存在，ID: " + id));
        
        // 使用手动转换方法
        return convertToDTO(book);
    }

    @Override
    public BookDTO findByIsbn(String isbn) {
        Book book = bookRepository.findByIsbn(isbn)
                .orElseThrow(() -> new RuntimeException("图书不存在，ISBN: " + isbn));
        return convertToDTO(book);
    }

    @Override
    public List<BookDTO> findAllBooks() {
        List<Book> books = bookRepository.findAll();
        return books.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public Page<BookDTO> findAllBooks(Pageable pageable) {
        Page<Book> bookPage = bookRepository.findAll(pageable);
        List<BookDTO> bookDTOs = bookPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(bookDTOs, pageable, bookPage.getTotalElements());
    }

    @Override
    public Page<BookDTO> findBooksByTitle(String title, Pageable pageable) {
        Page<Book> bookPage = bookRepository.findByTitleContainingIgnoreCase(title, pageable);
        List<BookDTO> bookDTOs = bookPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(bookDTOs, pageable, bookPage.getTotalElements());
    }

    @Override
    public Page<BookDTO> findBooksByAuthor(String author, Pageable pageable) {
        Page<Book> bookPage = bookRepository.findByAuthorContainingIgnoreCase(author, pageable);
        List<BookDTO> bookDTOs = bookPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(bookDTOs, pageable, bookPage.getTotalElements());
    }

    @Override
    public Page<BookDTO> findBooksByCategory(String category, Pageable pageable) {
        Page<Book> bookPage = bookRepository.findByCategoryContainingIgnoreCase(category, pageable);
        List<BookDTO> bookDTOs = bookPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(bookDTOs, pageable, bookPage.getTotalElements());
    }

    @Override
    public Page<BookDTO> searchBooks(String keyword, Pageable pageable) {
        Page<Book> bookPage = bookRepository.searchBooks(keyword, pageable);
        List<BookDTO> bookDTOs = bookPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return new PageImpl<>(bookDTOs, pageable, bookPage.getTotalElements());
    }

    @Override
    public List<BookDTO> findAvailableBooks() {
        List<Book> books = bookRepository.findByAvailableQuantityGreaterThan(0);
        return books.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public BookDTO saveBook(BookDTO bookDTO) {
        Book book;
        
        if (bookDTO.getId() != null) {
            // 更新现有图书
            book = bookRepository.findById(bookDTO.getId())
                    .orElseThrow(() -> new RuntimeException("图书不存在，ID: " + bookDTO.getId()));
            
            // 更新字段
            book.setTitle(bookDTO.getTitle());
            book.setAuthor(bookDTO.getAuthor());
            book.setPublisher(bookDTO.getPublisher());
            book.setPublicationYear(bookDTO.getPublicationYear());
            book.setIsbn(bookDTO.getIsbn());
            book.setCategory(bookDTO.getCategory());
            book.setDescription(bookDTO.getDescription());
            book.setQuantity(bookDTO.getQuantity());
            book.setAvailableQuantity(bookDTO.getAvailableQuantity());
        } else {
            // 创建新图书
            book = convertToEntity(bookDTO);
            // 对于新书，如果没有设置可用数量，则默认等于总数量
            if (book.getAvailableQuantity() == null) {
                book.setAvailableQuantity(book.getQuantity());
            }
        }
        
        Book savedBook = bookRepository.save(book);
        return convertToDTO(savedBook);
    }

    @Override
    @Transactional
    public void deleteBook(Integer id) {
        if (!bookRepository.existsById(id)) {
            throw new RuntimeException("图书不存在，ID: " + id);
        }
        bookRepository.deleteById(id);
    }

    @Override
    public boolean isBookAvailable(Integer id) {
        Book book = bookRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("图书不存在，ID: " + id));
        return book.getAvailableQuantity() > 0;
    }

    @Override
    @Transactional
    public void updateBookQuantity(Integer id, int quantityChange) {
        Book book = bookRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("图书不存在，ID: " + id));
        
        int newAvailableQuantity = book.getAvailableQuantity() + quantityChange;
        
        if (newAvailableQuantity < 0) {
            throw new RuntimeException("图书可用数量不足，无法借出");
        }
        
        if (newAvailableQuantity > book.getQuantity()) {
            throw new RuntimeException("可用数量不能超过总数量");
        }
        
        book.setAvailableQuantity(newAvailableQuantity);
        bookRepository.save(book);
    }
    
    @Override
    public long countBooks() {
        return bookRepository.count();
    }
    
    // 手动实现从实体到DTO的转换
    private BookDTO convertToDTO(Book book) {
        if (book == null) {
            return null;
        }
        
        BookDTO dto = new BookDTO();
        dto.setId(book.getId());
        dto.setTitle(book.getTitle());
        dto.setAuthor(book.getAuthor());
        dto.setPublisher(book.getPublisher());
        dto.setPublicationYear(book.getPublicationYear());
        dto.setIsbn(book.getIsbn());
        dto.setCategory(book.getCategory());
        dto.setDescription(book.getDescription());
        dto.setQuantity(book.getQuantity());
        dto.setAvailableQuantity(book.getAvailableQuantity());
        dto.setCreatedAt(book.getCreatedAt());
        dto.setUpdatedAt(book.getUpdatedAt());
        
        return dto;
    }
    
    // 手动实现从DTO到实体的转换
    private Book convertToEntity(BookDTO dto) {
        if (dto == null) {
            return null;
        }
        
        Book book = new Book();
        book.setId(dto.getId());
        book.setTitle(dto.getTitle());
        book.setAuthor(dto.getAuthor());
        book.setPublisher(dto.getPublisher());
        book.setPublicationYear(dto.getPublicationYear());
        book.setIsbn(dto.getIsbn());
        book.setCategory(dto.getCategory());
        book.setDescription(dto.getDescription());
        book.setQuantity(dto.getQuantity());
        book.setAvailableQuantity(dto.getAvailableQuantity());
        book.setCreatedAt(dto.getCreatedAt());
        book.setUpdatedAt(dto.getUpdatedAt());
        
        return book;
    }
}
